import os
import sys
import Image

from django.db import connection
from django.conf import settings
from django.template.defaultfilters import safe


def create_prev_current_next(orderby):
    orderby_name = (orderby[0] == '-') and orderby[1:] or orderby
    def prev_current_next(self, objects, limit):
        self_orderby = getattr(self, orderby_name)

        lt_kwargs = {'%s__lt' % orderby_name: self_orderby }
        gt_kwargs = {'%s__gt' % orderby_name: self_orderby }

        if orderby[0] == '-':
            prevs = objects.filter(**gt_kwargs).order_by(orderby[1:])
            nexts = objects.filter(**lt_kwargs).order_by(orderby)
        else:
            prevs = objects.filter(**lt_kwargs).order_by('-' + orderby)
            nexts = objects.filter(**gt_kwargs).order_by(orderby)

        prevs = prevs[:limit*2]
        nexts = nexts[:limit*2]

        if len(prevs) < limit:
            nexts = nexts[:limit*2 - len(prevs)]
        else:
            nexts = nexts[:limit]

        if len(nexts) < limit:
            prevs = prevs[:limit*2 - len(nexts)]
        else:
            prevs = prevs[:limit]

        return list(reversed(prevs)) + [self] + list(nexts)
    return prev_current_next

def create_min(*args, **kwargs):
    return create_aggregation('min', *args, **kwargs)

def create_max(*args, **kwargs):
    return create_aggregation('max', *args, **kwargs)

def create_aggregation(func, field):
    qn = connection.ops.quote_name
    @classmethod
    def aggregation(cls):
        cursor = connection.cursor()
        sql = """SELECT %s(%s) FROM %s AS res""" % (
            func, qn('count'), qn('%s_%s' % (cls._meta.app_label, cls.__name__)).lower(),
        )
        cursor.execute(sql)
        row = cursor.fetchone()
        return row[0]
    return aggregation

def get_icon(image, alt, icons_path, size, force=False, resizer=None):
    filename = os.path.basename(image.path)
    icon_mean_path = icons_path + ('%dx%d-' % size) + filename
    icon_path = os.path.join(settings.MEDIA_ROOT, icon_mean_path)
    size = tuple(x or sys.maxint for x in size)
    if force or not os.path.exists(icon_path):
        img = Image.open(image.path)
        if resizer is None:
            img.thumbnail(size, Image.ANTIALIAS)
        else:
            img = resizer(img, size)
        img.save(icon_path)
        w, h = img.size
    else:
        w, h = Image.open(icon_path).size
    return safe('<img src="%s" width="%d" height="%d" alt="%s" title="%s">' %
        (settings.MEDIA_URL + icon_mean_path, w, h, alt, alt))

def resize_if_needs(imgfield, size):
    """For usage in save() method"""
    if not imgfield: return

    img = Image.open(imgfield.path)
    if imgfield.size > size:
        img.thumbnail(size, Image.ANTIALIAS)
        img.save(imgfield.path)

from django.utils.functional import lazy
def lazy_args(txt, args):
    """work as ugettext_lazy(): substitute params only on output"""
    return lazy(lambda args: txt % args, unicode)(args)

def create_abstract_model(model, exclude_fields=('id'), exclude_methods=()):
    """Convert existing model to abstract equivalent
    (model with Meta.abstract = True)"""
    fields = dict((f.attname, f) for f in model._meta.fields if
        f.attname not in exclude_fields)

    good_magic = ('__unicode__',)
    methods = {}
    for prop in dir(model):
        try:
            func = getattr(model, prop).im_func
        except AttributeError:
            continue

        name = func.func_name
        if ((not name.startswith('_') or name in good_magic) and
            name not in exclude_methods
        ):
            methods[name] = func

    class Base(ModelBase):
        def __new__(cls, name, bases, attrs):
            if name == 'AbstractModel':
                attrs.update(fields)
                attrs.update(methods)
            return super(Base, cls).__new__(cls, name, bases, attrs)

    class AbstractModel(models.Model):
        __metaclass__ = Base
        class Meta(model.Meta):
            abstract = True

    return AbstractModel
